use serde::{Deserialize, Serialize};
use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};

use model_graph_types::{
    container::context::Context,
    database::DataSource,
    datasource::{
        DataSourceConnector, DataSourceProvider, DeleteCondition, DeleteOptions,
        GetDataSourceOptions, InsertOptions, QueryCondition, QueryExtention, QueryOptions,
        UpdateCondition, UpdateOptions,
    },
    modeling::{Class, MetaConnector, PagingResponse, Value},
};

use crate::{connector::SimpleDataSourceConnector, modeling_connector::SimpleMetaConnector};

pub async fn get_class(
    _context: Arc<Mutex<Context>>,
    class_identifier: &String,
) -> anyhow::Result<Class> {
    //查询
    Ok(SimpleMetaConnector::default()
        .get_class(class_identifier)
        .await?)
}

pub async fn meta_domain_classes(
    _context: Arc<Mutex<Context>>,
    domain_identifier: &String,
) -> anyhow::Result<Vec<Class>> {
    //查询
    Ok(SimpleMetaConnector::default()
        .domain_classes(domain_identifier)
        .await?)
}

pub async fn get_instance_by_id(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    clazz: &String,
    id: &String,
) -> anyhow::Result<serde_json::Value> {
    //查询
    let instance = SimpleDataSourceConnector::default()
        .instance_query_one_by_keys(meta_datasource, datasource, clazz, vec![id.clone()])
        .await?;

    Ok(instance.try_into()?)
}

pub async fn get_instance(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    class_identifier: &String,
    conditions: QueryCondition,
    extentions: Option<QueryExtention>,
    options: Option<QueryOptions>,
) -> anyhow::Result<serde_json::Value> {
    //查询
    let instance = SimpleDataSourceConnector::default()
        .instance_query_one(
            meta_datasource,
            datasource,
            class_identifier,
            conditions,
            extentions,
            options,
        )
        .await?;

    Ok(instance.try_into()?)
}

pub async fn get_instances(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    class_identifier: &String,
    conditions: QueryCondition,
    extentions: Option<QueryExtention>,
    options: Option<QueryOptions>,
) -> anyhow::Result<PagingResponse<Vec<serde_json::Value>>> {
    //查询
    let instance = SimpleDataSourceConnector::default()
        .instance_query(
            meta_datasource,
            datasource,
            class_identifier,
            conditions,
            extentions,
            options,
        )
        .await?;
    let mut data: Vec<serde_json::Value> = vec![];
    let total = instance.total;
    for v in instance.data {
        data.push(v.try_into()?);
    }

    Ok(PagingResponse {
        total: total,
        data: data,
    })
}
pub async fn post_instance(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    class_identifier: &String,
    src_values: HashMap<String, serde_json::Value>,
    options: Option<InsertOptions>,
) -> anyhow::Result<serde_json::Value> {
    let mut values = HashMap::new();

    for (key, value) in src_values {
        values.insert(key, value.try_into()?);
    }
    //查询
    let instance = SimpleDataSourceConnector::default()
        .instance_insert(
            meta_datasource,
            datasource,
            class_identifier,
            values,
            options,
        )
        .await?;

    Ok(instance.try_into()?)
}

pub async fn put_instance(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    class_identifier: &String,
    conditions: UpdateCondition,
    src_values: HashMap<String, serde_json::Value>,
    options: Option<UpdateOptions>,
) -> anyhow::Result<serde_json::Value> {
    let mut values = HashMap::new();

    for (key, value) in src_values {
        values.insert(key, value.try_into()?);
    }
    //查询
    let instance = SimpleDataSourceConnector::default()
        .instance_update(
            meta_datasource,
            datasource,
            class_identifier,
            conditions,
            values,
            options,
        )
        .await?;

    Ok(instance.try_into()?)
}

pub async fn put_instance_by_keys(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    class_identifier: &String,
    keys: Vec<String>,
    src_values: HashMap<String, serde_json::Value>,
    options: Option<UpdateOptions>,
) -> anyhow::Result<serde_json::Value> {
    let mut values = HashMap::new();

    for (key, value) in src_values {
        values.insert(key, value.try_into()?);
    }
    //查询
    let instance = SimpleDataSourceConnector::default()
        .instance_update_by_keys(
            meta_datasource,
            datasource,
            class_identifier,
            keys,
            values,
            options,
        )
        .await?;

    Ok(instance.try_into()?)
}

pub async fn instance_delete_by_keys(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    class_identifier: &String,
    conditions: Vec<String>,
    options: Option<DeleteOptions>,
) -> anyhow::Result<serde_json::Value> {
    //查询
    let instance = SimpleDataSourceConnector::default()
        .instance_delete_by_keys(
            meta_datasource,
            datasource,
            class_identifier,
            conditions,
            options,
        )
        .await?;

    Ok(instance.try_into()?)
}

pub async fn instance_count(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    class_identifier: &String,
    conditions: QueryCondition,
    options: Option<QueryOptions>,
) -> anyhow::Result<serde_json::Value> {
    //查询
    let instance: u32 = SimpleDataSourceConnector::default()
        .instance_count(
            meta_datasource,
            datasource,
            class_identifier,
            conditions,
            options,
        )
        .await?;

    Ok(instance.try_into()?)
}

pub async fn instance_delete(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    class_identifier: &String,
    conditions: DeleteCondition,
    options: Option<DeleteOptions>,
) -> anyhow::Result<serde_json::Value> {
    //查询
    let instance = SimpleDataSourceConnector::default()
        .instance_delete(
            meta_datasource,
            datasource,
            class_identifier,
            conditions,
            options,
        )
        .await?;

    Ok(instance.try_into()?)
}

pub async fn batch_instance_delete(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    items: Vec<(String, DeleteCondition)>,
    options: Option<DeleteOptions>,
) -> anyhow::Result<Vec<serde_json::Value>> {
    //查询
    let values = SimpleDataSourceConnector::default()
        .batch_instance_delete(meta_datasource, datasource, items, options)
        .await?;

    let mut res: Vec<serde_json::Value> = vec![];
    for value in values {
        res.push(value.try_into()?);
    }
    Ok(res)
}

pub async fn batch_instance_update(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    items: Vec<(String, UpdateCondition, HashMap<String, Value>)>,
    options: Option<UpdateOptions>,
) -> anyhow::Result<Vec<serde_json::Value>> {
    //查询
    let values = SimpleDataSourceConnector::default()
        .batch_instance_update(meta_datasource, datasource, items, options)
        .await?;

    let mut res: Vec<serde_json::Value> = vec![];
    for value in values {
        res.push(value.try_into()?);
    }
    Ok(res)
}

pub async fn batch_instance_insert(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    items: Vec<(String, HashMap<String, Value>)>,
    options: Option<InsertOptions>,
) -> anyhow::Result<Vec<serde_json::Value>> {
    //查询
    let values = SimpleDataSourceConnector::default()
        .batch_instance_insert(meta_datasource, datasource, items, options)
        .await?;

    let mut res: Vec<serde_json::Value> = vec![];
    for value in values {
        res.push(value.try_into()?);
    }
    Ok(res)
}

pub async fn batch_instance_query(
    context: Arc<Mutex<Context>>,
    meta_datasource: &Option<DataSource>,
    datasource: &DataSource,
    items: Vec<(String, QueryCondition, Option<QueryExtention>)>,
    options: Option<QueryOptions>,
) -> anyhow::Result<Vec<PagingResponse<Vec<serde_json::Value>>>> {
    //获取到数据源
    let mut result: Vec<PagingResponse<Vec<serde_json::Value>>> = vec![];
    for (s, c, e) in items {
        result.push(
            get_instances(
                context.clone(),
                meta_datasource,
                datasource,
                &s,
                c,
                e,
                options.clone(),
            )
            .await?,
        );
    }
    Ok(result)
}
